package com.feeyo.groundservice.composewidget.view.slidebar

import androidx.compose.animation.animateColorAsState
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.border
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.Dp
import com.feeyo.groundservice.base_util.SuccessOrFailCallback
import com.feeyo.groundservice.composewidget.R
import com.feeyo.groundservice.composewidget.util.dimenToDp
import com.feeyo.groundservice.composewidget.util.dimenToSp
import com.feeyo.groundservice.composewidget.util.toComposeColor
import com.feeyo.groundservice.composewidget.view.compose_pager.ComposePager
import com.feeyo.groundservice.composewidget.view.compose_pager.ComposePagerState
import com.feeyo.groundservice.composewidget.view.compose_pager.IPageChange
import kotlin.math.abs

/**
 *作者：QLH on 2024-10-29
 *描述：自定义滑块
 */


/***
 * 固定格式滑块
 *
 * @param title 标题
 * @param slideWidth 宽度
 * @param slideHeight 高度
 * @param threshold 滑动成功阈值
 * @param barBg 背景色
 * @param txtColors 文字颜色:变化的2种颜色
 * @param onDragEnd 回调
 * @param dragListenerNeedUpdateFlag 手势监听需要更新状态，防止旧值问题，一般给出一个新的标识，比如data.id
 * **/
@Composable
fun FixSlideBar(
    title: String,
    slideWidth: Dp = R.dimen.d200.dimenToDp(),
    slideHeight: Dp = R.dimen.d40.dimenToDp(),
    threshold: Float = 0.7f,
    barBg: Color = R.color.blue_2E76EE.toComposeColor(),
    txtColors: List<Color> = arrayListOf(R.color.white.toComposeColor(), barBg),
    onDragEnd: (SuccessOrFailCallback) -> Unit,
    dragListenerNeedUpdateFlag: String = title,// //手势监听需要更新状态，防止旧值问题
) {
    //背景进度的宽度
    val maskWidth = remember { mutableStateOf(slideHeight) }
    //检测是否超出文字区域：文字变色使用的
    val beyond = remember { mutableStateOf(false) }

    val txtColor = animateColorAsState(
        if (beyond.value) txtColors[0] else txtColors[1], label = ""
    )
    val txtWidth = remember { mutableIntStateOf(0) }

    val callback = object : SuccessOrFailCallback {
        override fun success() {
            //复原
            maskWidth.value = slideHeight
            beyond.value = false
        }

        override fun fail() {
            //复原
            maskWidth.value = slideHeight
            beyond.value = false
        }
    }

    Box(
        modifier = Modifier.size(slideWidth, slideHeight)
    ) {
        //内容
        Box(
            modifier = Modifier.fillMaxSize()
                .clip(CircleShape)
                .border(
                    width = R.dimen.d2.dimenToDp(),
                    color = barBg,
                    shape = CircleShape
                ),
            contentAlignment = Alignment.Center
        ) {
            Box(
                modifier = Modifier.fillMaxSize(),
                contentAlignment = Alignment.Center
            ) {
                Layout(
                    content = {
                        Text(
                            text = title,
                            fontSize = R.dimen.d14.dimenToSp(),
                            fontWeight = FontWeight.W400,
                            color = txtColor.value,
                            maxLines = 1,
                            modifier = Modifier.align(Alignment.Center)
                                .basicMarquee(Int.MAX_VALUE)
                        )
                    },
                    measurePolicy = { measurables, constraints ->
                        val placeable =
                            measurables.single().measure(constraints)
                        layout(placeable.width, placeable.height) {
                            placeable.placeRelative(0, 0)
                            txtWidth.intValue = placeable.width
                        }
                    }
                )
            }

        }
        //遮罩层
        Box(
            modifier = Modifier.size(maskWidth.value, slideHeight)
                .padding(R.dimen.d4.dimenToDp())
                .background(
                    color = barBg,
                    shape = CircleShape
                ),
            contentAlignment = Alignment.CenterEnd
        ) {
            Image(
                painter = painterResource(id = R.drawable.icon_slide_bar_arrow),
                contentDescription = "",
                contentScale = ContentScale.Inside,
                modifier = Modifier.size(R.dimen.d23.dimenToDp())
                    .padding(end = R.dimen.d6.dimenToDp())
            )
        }

        //遮住后的文本
        if (beyond.value) {
            Text(
                text = title,
                fontSize = R.dimen.d14.dimenToSp(),
                fontWeight = FontWeight.W400,
                color = txtColor.value,
                maxLines = 1,
                modifier = Modifier.align(Alignment.Center)
                    .basicMarquee(Int.MAX_VALUE)
            )
        }

        //滑动控件
        Box(
            modifier = Modifier.fillMaxSize()
                .pointerInput(dragListenerNeedUpdateFlag) {
                    detectDragGestures(
                        onDragEnd = {
                            //检测是否超过阈值
                            if (maskWidth.value / slideWidth > threshold) {
                                //直接画到最大值
                                maskWidth.value = slideWidth
                                //触发回调
                                onDragEnd(callback)
                            } else {
                                callback.fail()
                            }
                        },
                        onDrag = { change, dragAmount ->
                            maskWidth.value += dragAmount.x.toDp()
                            //修正一下
                            maskWidth.value = maskWidth.value.let {
                                //最小宽度
                                if (it < slideHeight)
                                    slideHeight
                                else if (it > slideWidth)
                                    slideWidth
                                else
                                    it
                            }
                            beyond.value =
                                maskWidth.value > (slideWidth + txtWidth.intValue.toDp()) / 2 + slideHeight
                        },
                    )
                }
        )

    }
}

/***
 * 自定义滑块
 *
 * @param slideWidth 宽度
 * @param slideHeight 高度
 * @param beyond 是否超过阈值
 * @param threshold 滑动成功阈值
 * @param barBg 背景色
 * @param content 内容
 * @param mask 遮罩
 * @param onDragEnd 回调
 * @param dragListenerNeedUpdateFlag 手势监听需要更新状态，防止旧值问题，一般给出一个新的标识，比如data.id
 * **/
@Composable
fun CustomSlideBar(
    slideWidth: Dp = R.dimen.d200.dimenToDp(),
    slideHeight: Dp = R.dimen.d40.dimenToDp(),
    beyond: MutableState<Boolean>,
    threshold: Float = 0.7f,
    barBg: Color = R.color.blue_2E76EE.toComposeColor(),
    content: @Composable BoxScope.() -> Unit,
    mask: @Composable (() -> Unit)? = null,
    onDragEnd: (SuccessOrFailCallback) -> Unit,
    dragListenerNeedUpdateFlag: String = "",// //手势监听需要更新状态，防止旧值问题
) {
    val maskWidth = remember { mutableStateOf(slideHeight) }

    val txtWidth = remember { mutableIntStateOf(0) }

    val callback = object : SuccessOrFailCallback {
        override fun success() {
            //复原
            maskWidth.value = slideHeight
            beyond.value = false
        }

        override fun fail() {
            //复原
            maskWidth.value = slideHeight
            beyond.value = false
        }
    }

    Box(
        modifier = Modifier.size(slideWidth, slideHeight)
    ) {
        //内容
        Box(
            modifier = Modifier.fillMaxSize()
                .clip(CircleShape)
                .border(
                    width = R.dimen.d2.dimenToDp(),
                    color = barBg,
                    shape = CircleShape
                ),
            contentAlignment = Alignment.Center
        ) {
            Box(
                modifier = Modifier.fillMaxSize(),
                contentAlignment = Alignment.Center
            ) {
                Layout(
                    content = { content() },
                    measurePolicy = { measurables, constraints ->
                        val placeable =
                            measurables.single().measure(constraints)
                        layout(placeable.width, placeable.height) {
                            placeable.placeRelative(0, 0)
                            txtWidth.intValue = placeable.width
                        }
                    }
                )
            }
        }
        //遮罩层
        Box(
            modifier = Modifier.size(maskWidth.value, slideHeight)
                .padding(R.dimen.d4.dimenToDp())
                .background(
                    color = barBg,
                    shape = CircleShape
                ),
            contentAlignment = Alignment.CenterEnd
        ) {
            mask?.invoke() ?: Image(
                painter = painterResource(id = R.drawable.icon_slide_bar_arrow),
                contentDescription = "",
                contentScale = ContentScale.Inside,
                modifier = Modifier.size(R.dimen.d23.dimenToDp())
                    .padding(end = R.dimen.d6.dimenToDp())
            )
        }

        //遮住后的文本
        if (beyond.value) {
            content()
        }

        //滑动控件
        Box(
            modifier = Modifier.fillMaxSize()
                .pointerInput(dragListenerNeedUpdateFlag) {
                    detectDragGestures(
                        onDragEnd = {
                            //检测是否超过阈值
                            if (maskWidth.value / slideWidth > threshold) {
                                //直接画到最大值
                                maskWidth.value = slideWidth
                                //触发回调
                                onDragEnd(callback)
                            } else {
                                callback.fail()
                            }
                        },
                        onDrag = { change, dragAmount ->
                            maskWidth.value += dragAmount.x.toDp()
                            //修正一下
                            maskWidth.value = maskWidth.value.let {
                                //最小宽度
                                if (it < slideHeight)
                                    slideHeight
                                else if (it > slideWidth)
                                    slideWidth
                                else
                                    it
                            }
                            beyond.value =
                                maskWidth.value > (slideWidth + txtWidth.intValue.toDp()) / 2 + slideHeight
                        }
                    )
                }
        )

    }
}


/**
 * 保障节点录入
 *
 *@param defaultIndex 默认选中项
 * @param cornerSize 圆角大小
 * @param threshold 滑动阈值,占宽度比例
 * @param userEnable 是否允许用户滑动
 * @param bgs 背景
 * @param isBorder 是否有边框
 * @param borderWidth 边框宽度
 * @param borderColor 边框颜色
 * **/
@Composable
fun GuaranteeNodeSlideBar(
    defaultIndex: Int = 0,
    cornerSize: Dp = R.dimen.d4.dimenToDp(),
    threshold: Float = 0.8f,
    userEnable: Boolean = true,
    bgs: List<Color> = listOf(
        R.color.blue_2E76EE.toComposeColor(),
        R.color.gray_99.toComposeColor()
    ),
    isBorder: Boolean = false,
    borderWidth: Dp = R.dimen.d1.dimenToDp(),
    borderColor: List<Color> = bgs,
    onCurrentPageIndex: (Int) -> Unit,
    onResumeIndex: (() -> Unit) -> Unit = {}
) {
    val pagerState = remember { ComposePagerState() }

    ComposePager(
        pageCount = bgs.size,
        composePagerState = pagerState,
        modifier = Modifier.fillMaxSize(),
        orientation = Orientation.Horizontal,
        pageCache = 2,
        thresholdRatio = threshold,
        userEnable = userEnable,
        pageChange = object : IPageChange {
            override fun onNextPage() {
                onCurrentPageIndex(pagerState.getCurrSelectIndex())
            }

            override fun onPrePage() {
                onCurrentPageIndex(pagerState.getCurrSelectIndex())
            }
        }
    ) {

        Box(
            modifier = Modifier.fillMaxSize()
                .background(
                    color = bgs[index],
                    shape = RoundedCornerShape(cornerSize)
                ).let {
                    if (isBorder)
                        it.border(
                            width = borderWidth,
                            color = borderColor[index],
                            shape = RoundedCornerShape(cornerSize)
                        )
                    else
                        it
                }
        )
    }

    //用于正向操作失败，回退使用的
    val resume = {
        pagerState.setPageIndex(abs(pagerState.getCurrSelectIndex() - 1))
    }

    //设置默认位置
    LaunchedEffect(Unit) {
        onResumeIndex(resume)
    }

    LaunchedEffect(defaultIndex) {
        pagerState.setPageIndex(defaultIndex)
    }

}